/*
 * Copyright 2011 www.pretty-tools.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "stdafx.h"
#include "StringBundle.h"
#include "ResourceResolver.h"

// CStringBundle

CStringBundle::CStringBundle()
{
    ATLTRACE( _T("CStringBundle::CStringBundle()\n") );
}

CStringBundle::~CStringBundle()
{
    ATLTRACE( _T("CStringBundle::~CStringBundle()\n") );
}

STDMETHODIMP CStringBundle::Init(BSTR url)
{
    ATLASSERT(url);
    ATLTRACE(L"CStringBundle::Init(%s)\n", url);

    CStringW strURL;
    RETURN_FAILED(ResourceResolver::ResolveURL(url, strURL))

    if (ResourceResolver::GetProtocol(strURL) == _T("res"))
    {
        CString strModule = ResourceResolver::GetModule(strURL);
        CString strResourceName = ResourceResolver::GetResourceName(strURL);
        if (strModule.IsEmpty() || strResourceName.IsEmpty())
            return E_FAIL;

        Library module(strModule);
        if (!module)
            return E_FAIL;

        HRSRC hResource = module.FindResource(strResourceName, _T("PROPERTIES"));
        if (!hResource) return E_FAIL;

        DWORD dwDataSize = module.SizeofResource(hResource);
        if (!dwDataSize) return E_FAIL;

        HGLOBAL hGlobal = module.LoadResource(hResource);
        if (!hGlobal) return E_FAIL;

        char* pData = (char*)LockResource(hGlobal);
        if (!pData)
        {
            FreeResource(hGlobal);
            return E_FAIL;
        }

        CStringA strData;
        memcpy(strData.GetBuffer(dwDataSize), pData, dwDataSize);
        strData.ReleaseBuffer(dwDataSize);

        bool bResult = m_properties.ParseString(strData);

        FreeResource(hGlobal), hGlobal = NULL;

        RETURN_E_FAIL_ON_FALSE(bResult);
    }
    else
    {
        RETURN_E_FAIL_ON_FALSE(m_properties.Load(strURL))
    }

    return S_OK;
}

STDMETHODIMP CStringBundle::GetStringFromName(BSTR name, BSTR* pRet)
{
    if (!name)
        return E_INVALIDARG;
    if (!pRet)
        return E_POINTER;
    if (m_properties.IsEmpty())
        return E_UNEXPECTED;

    ATLTRACE( L"CStringBundle::GetStringFromName(\"%s\")\n", name );

    CString strValue = m_properties[name];

    *pRet = CComBSTR(strValue).Detach();

    return strValue.IsEmpty() ? S_FALSE : S_OK;
}

STDMETHODIMP CStringBundle::getSimpleEnumeration(ISimpleEnumerator** pEnumeration)
{
    if (!pEnumeration)
        return E_POINTER;
    if (m_properties.IsEmpty())
        return E_UNEXPECTED;

    ATLTRACE( _T("CStringBundle::getSimpleEnumeration() - %i elements\n"), m_properties.GetCount());

    CComPtr<ISimpleEnumerator> enumerator;
    RETURN_FAILED(enumerator.CoCreateInstance(CLSID_SimpleEnumerator))

    const CAtlMap<CString, CString>& prop = m_properties.GetMap();

    CComSafeArray<VARIANT> arValues;
    RETURN_FAILED(arValues.Create(prop.GetCount()))

    int iPos = 0;
    for (POSITION pos = prop.GetStartPosition(); pos; )
    {
        CString strKey, strValue;
        prop.GetNextAssoc(pos, strKey, strValue);

        CComPtr<IPropertyElement> elem;
        RETURN_FAILED(elem.CoCreateInstance(CLSID_PropertyElement))
        RETURN_FAILED(elem->put_key(CComVariant(strKey)))
        RETURN_FAILED(elem->put_value(CComVariant(strValue)))

        arValues[iPos++] = elem;
    }

    CComVariant vtValues;
    vtValues.vt = VT_ARRAY | VT_VARIANT;
	vtValues.parray = arValues.Detach();

    RETURN_FAILED(enumerator->Init(vtValues))

    *pEnumeration = enumerator.Detach();

    return S_OK;
}
